package com.myk.game.gobangchess.ai.symmetricstatic;// package com.myk.game.gobangchess.ai.symmetric;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;

public class main_DCQ_v7 {

    static double[] paras1 = {
        1.344603, 0.836316, 0.588273, 1.601414, 1.778030, 1.470500, 1.575575, 1.360726, 
        1.966466, 1.198838, 0.669700, 1.133773, 1.681551, 1.181874, 0.519899, 0.586119, 
        1.299460, 1.640249, 1.576184, 1.775767, 1.702252, 0.988008, 1.131254, 0.926918, 
        1.129857, 1.399168, 1.009128, 1.657710, 1.881047, 1.440165
    };
    static double total_count_para = 0;
    static int cut1 = 0;
    static double total_count_para2 = 0;
    static double total_count_para3 = 0;
    public static void main(String[] args) {
        

        // 示例输入棋盘（
        int[][] board = {
                { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0},
                { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0},
                { 0, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0,-1, 0, 0, 1},
                { 0, 0, 0, 0,-1,-1, 0,-1,-1, 0, 0, 0, 0, 0, 1},
                {-1,-1, 0, 0,-1,-1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
                { 0,-1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,-1,-1},
                { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,-1,-1},
                { 0, 0, 1, 0, 0, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0},
                { 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                { 0,-1, 0,-1, 0, 0, 0, 0, 0, 0,-1, 0, 0, 1, 1},
                { 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0,-1, 0},
                { 0,-1, 1,-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,-1},
                { 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1,-1, 0},
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}
        };
        // int[][] board = {
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        // };
        // int[][] board = {
        //     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 0},
        //     { 0,-1, 1, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0},
        //     { 0,-1, 1, 1, 0, 0, 1, 0, 1, 0,-1, 0,-1, 0, 0},
        //     { 0, 0,-1,-1, 0, 1,-1, 0, 0, 1, 0, 1, 1, 0, 0},
        //     { 0, 0, 0, 0, 1,-1, 0, 0, 1, 0, 0, 0, 1, 0, 0},
        //     { 0, 0, 0, 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        //     { 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0},
        //     { 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0},
        //     { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        //     { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
        //     { 0, 0,-1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0},
        //     {-1,-1,-1,-1, 0, 1, 0, 0, 1, 0, 1, 0,-1, 0, 0},
        //     { 0, 0,-1, 0, 0, 0, 1, 0, 0, 0,-1,-1,-1,-1,-1},
        //     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0}
        // };

        // 示例部分
        // 打印原始棋盘
        System.out.println("原始棋盘:");
        printBoard(board);
        long startTime = System.nanoTime();

        // 执行目标方法
        int difficulty = 3; // 取值：1、2、3，分别为简单、普通、困难
        ActionResult bestAction = DCQ_engine_v4(board, difficulty);


        // 记录结束时间
        long endTime = System.nanoTime();
        long duration = endTime - startTime;
        System.out.println("\n"+difficulty+"时间: " + (duration / 1_000_000.0) + " 毫秒");

        // 为了展示动作在棋盘上的标注，重新打印棋盘，并对相关位置进行着色
        printBoardWithAction(board, bestAction);

        // 输出最终选择的动作和分数
        System.out.println("最终选择的动作分数: " + bestAction.score);
        System.out.println("落子位置: (" + bestAction.placePos[0] + "," + bestAction.placePos[1] + ")");
        System.out.println("被拉子位置: (" + bestAction.pullPos[0] + "," + bestAction.pullPos[1] + ")");
        System.out.println("拉子结果位置: (" + bestAction.targetPos[0] + "," + bestAction.targetPos[1] + ")");


        

        // BlockData blockData = storeBlocks(board);

        // // 调用打分函数
        // double score = calculateScore(
        //         blockData.ownBlockCount,
        //         blockData.opponentBlockCount,
        //         blockData.ownBlockInfluence,
        //         blockData.opponentBlockInfluence,
        //         blockData.ownBlockPositions,
        //         blockData.opponentBlockPositions,
        //         blockData.ownBlockPieceCounts,
        //         blockData.opponentBlockPieceCounts,
        //         blockData.ownBlockSymmetry,
        //         blockData.opponentBlockSymmetry
        // );
        // System.out.println(score);






        // /////实验部分
        // int win_1 = 0;
        // int win_2 = 0;
        // int gamenum = 5;
        // int[] allround = new int[gamenum];

        // for(int r = 0; r<gamenum; r++){
            
        //     board = new int[15][15];

        //     int round = 0;
        //     while(true){
        //         round += 1;
        //         long startTime = System.nanoTime();

        //         ActionResult bestAction = DCQ_engine_v4(board, 3);

        //         // 记录结束时间
        //         long endTime = System.nanoTime();
        //         long duration = endTime - startTime;
        //         System.out.println("\n"+2+"时间: " + (duration / 1_000_000.0) + " 毫秒");

        //         board = executeAction(board, bestAction.placePos, bestAction.pullPos, bestAction.targetPos);

        //         // 为了展示动作在棋盘上的标注，重新打印棋盘，并对相关位置进行着色
        //         printBoardWithAction(board, bestAction);

        //         if(bestAction.score < -50000){
        //             System.out.println("\n2方败, 轮次："+round+", 已进行："+r);
        //             win_1 += 1;
        //             allround[r] = round;
        //             break;
        //         }


        //         // 旧方
        //         round += 1;
        //         board = reverseColors(board);

        //         startTime = System.nanoTime();


        //         main_DCQ_v6.ActionResult bestAction_old = main_DCQ_v6.DCQ_engine_v4(board, 3);
        //         // ActionResult bestAction_old = DCQ_engine_v2(board, 0);

        //         // 记录结束时间
        //         endTime = System.nanoTime();
        //         duration = endTime - startTime;

        //         System.out.println("\n"+1+"时间: " + (duration / 1_000_000.0) + " 毫秒");

        //         board = executeAction(board, bestAction_old.placePos, bestAction_old.pullPos, bestAction_old.targetPos);

        //         if(bestAction_old.score < -50000){
        //             System.out.println("\n1方败, 轮次："+round+", 已进行："+r);
        //             win_2 += 1;
        //             allround[r] = round;
        //             break;
        //         }
        //         board = reverseColors(board);

        //     }
        // }

        // System.out.println("1方胜次数："+win_1);
        // System.out.println("2方胜次数："+win_2);
        // System.out.println("平均轮次："+doubleArrAverage(allround));





        /////////////////
    }

    public static double doubleArrAverage(int[] arr) {
        double sum = 0;
        for(int i = 0;i < arr.length; i++) {
        sum += arr[i];
        }
        return sum / arr.length;
        }

    /**
     * 打印棋盘矩阵
     *
     * @param board 15x15棋盘矩阵
     */
    public static void printBoard(int[][] board) {
        for (int[] row : board) {
            for (int cell : row) {
                if (cell == 1) {
                    System.out.print(" 1 ");
                } else if (cell == -1) {
                    System.out.print(" -1 ");
                } else {
                    System.out.print(" 0 ");
                }
            }
            System.out.println();
        }
    }

    /**
     * 选择最佳动作的结果类
     */
    public static class ActionResult {
        double score;     // 局面分数
        int[] placePos;   // 落子位置 [x, y]
        int[] pullPos;    // 拉子位置 [x, y]
        int[] targetPos;  // 拉子目标位置 [x, y]

        public ActionResult(double score, int[] placePos, int[] pullPos, int[] targetPos) {
            this.score = score;
            this.placePos = placePos;
            this.pullPos = pullPos;
            this.targetPos = targetPos;
        }

        public int[] getPlacePos() {
            return placePos;
        }


        public int[] getPullPos() {
            return pullPos;
        }

        public int[] getTargetPos() {
            return targetPos;
        }
    }

    public static ActionResult  DCQ_engine_v4(int[][] board, int difficulty){
        total_count_para = count_total_num(board);
        total_count_para2 = 0.05;
        if(total_count_para>5){
            total_count_para2 += 0.05+0.03*(total_count_para - 5);
        }
        total_count_para3 = 0;
        if(total_count_para<20){
            total_count_para3 -= 0.02*(20-total_count_para);
        }
            
        if(difficulty == 0){
            return calculateOptimalAction_0(board);
        }
        if(difficulty == 1){
            return calculateOptimalAction_1(board);
        }
        if(difficulty == 2){
            return calculateOptimalAction_2(board);
        }
        if(difficulty == 3){
            // if(total_count_para<25){
            //     return calculateOptimalAction_1(board);
            // }
            return calculateOptimalAction_4(board);
        }
        return calculateOptimalAction_3(board);
    }
    /**
     * 计算最佳动作的复合函数
     *
     * @param board 当前棋盘矩阵（15x15）
     * @return 包含最佳动作的ActionResult对象
     */
    public static ActionResult calculateOptimalAction_0(int[][] board) {

        // 初始状态
        BlockData blockDataInitial = storeBlocks(board);

        // 调用打分函数
        double scorecheck = calculateScore(
            blockDataInitial.ownBlockCount,
            blockDataInitial.opponentBlockCount,
            blockDataInitial.ownBlockInfluence,
            blockDataInitial.opponentBlockInfluence,
            blockDataInitial.ownBlockPositions,
            blockDataInitial.opponentBlockPositions,
            blockDataInitial.ownBlockPieceCounts,
            blockDataInitial.opponentBlockPieceCounts,
            blockDataInitial.ownBlockSymmetry,
            blockDataInitial.opponentBlockSymmetry
        );
        
    
        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;
        if(total_count_para>30){
            cut = 1;
        }

        LegalActionData actionData = generateLegalActions(board,cut,ifsym);

        int actionCount = actionData.actionCount;

        // 分数向量
        double[] scores = new double[actionCount];

        // 遍历每个合法动作，进行一层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDataInitial, placePos, pullPos, targetPos, update_mode);


            // 调用打分函数
            scores[i] = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );
            if(total_count_para>10){
                scores[i] -= 0.04*update_mode*(total_count_para-10);
            }
        }
        // 找出最大分的下标
        int maxIndex = -1;  // 用于存储最大值的下标
        double maxScore = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxIndex = i; // 更新最大值的下标
            }
        }
        if(maxScore<5000){
            scores[maxIndex] = -99999;
        }


        double chosenScore = scores[maxIndex];
        int[] chosenPlacePos = actionData.placePositions.get(maxIndex);
        int[] chosenPullPos = actionData.pullPositions.get(maxIndex);
        int[] chosenTargetPos = actionData.targetPositions.get(maxIndex);

        return new ActionResult(chosenScore, chosenPlacePos, chosenPullPos, chosenTargetPos);
    }

    public static ActionResult calculateOptimalAction_1(int[][] board) {


        // 初始状态
        BlockData blockDataInitial = storeBlocks(board);

        // 调用打分函数
        double scorecheck = calculateScore(
            blockDataInitial.ownBlockCount,
            blockDataInitial.opponentBlockCount,
            blockDataInitial.ownBlockInfluence,
            blockDataInitial.opponentBlockInfluence,
            blockDataInitial.ownBlockPositions,
            blockDataInitial.opponentBlockPositions,
            blockDataInitial.ownBlockPieceCounts,
            blockDataInitial.opponentBlockPieceCounts,
            blockDataInitial.ownBlockSymmetry,
            blockDataInitial.opponentBlockSymmetry
        );
    
        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;
        LegalActionData actionData = generateLegalActions(board,cut,ifsym);

        int actionCount = actionData.actionCount;

        // 分数向量
        double[] scores = new double[actionCount];
        double[] scorescheck1 = new double[actionCount];


        // 遍历每个合法动作，进行一层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // // 调用更新合法行动结果函数，得到更新后的棋盘
            // int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            // // 分块存储
            // BlockData blockData = storeBlocks(updatedBoard);

            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDataInitial, placePos, pullPos, targetPos, update_mode);


            // 调用打分函数
            scorescheck1[i] = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );
            if(total_count_para>10){
                scorescheck1[i] -= 0.04*update_mode*(total_count_para-10);
            }
        }

        // 检查数组长度
        if (scorescheck1.length > 13) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck1, scorescheck1.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 13];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck1.length; i++) {
                if (scorescheck1[i] < threshold) {
                    scorescheck1[i] = -99999;
                }
            }
        }

        // 二层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck1[i]>=5000){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                ActionResult bestAction = calculateOptimalAction_0(reversedBoard);
                scores[i] = -bestAction.score;

            }else{
                scores[i] = -99999;
            }
        }


        // 找出最大分的下标
        int maxIndex = -1;  // 用于存储最大值的下标
        double maxScore = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxIndex = i; // 更新最大值的下标
            }
        }


        double chosenScore = scores[maxIndex];
        int[] chosenPlacePos = actionData.placePositions.get(maxIndex);
        int[] chosenPullPos = actionData.pullPositions.get(maxIndex);
        int[] chosenTargetPos = actionData.targetPositions.get(maxIndex);

        return new ActionResult(chosenScore, chosenPlacePos, chosenPullPos, chosenTargetPos);
    }

    public static ActionResult calculateOptimalAction_2(int[][] board) {


        // 初始状态
        BlockData blockDataInitial = storeBlocks(board);

        // 调用打分函数
        double scorecheck = calculateScore(
            blockDataInitial.ownBlockCount,
            blockDataInitial.opponentBlockCount,
            blockDataInitial.ownBlockInfluence,
            blockDataInitial.opponentBlockInfluence,
            blockDataInitial.ownBlockPositions,
            blockDataInitial.opponentBlockPositions,
            blockDataInitial.ownBlockPieceCounts,
            blockDataInitial.opponentBlockPieceCounts,
            blockDataInitial.ownBlockSymmetry,
            blockDataInitial.opponentBlockSymmetry
        );
    
        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;
        LegalActionData actionData = generateLegalActions(board,cut,ifsym);

        int actionCount = actionData.actionCount;

        // 分数向量
        double[] scores = new double[actionCount];
        double[] scorescheck1 = new double[actionCount];
        double[] scorescheck2 = new double[actionCount];


        // 遍历每个合法动作，进行一层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDataInitial, placePos, pullPos, targetPos, update_mode);


            // 调用打分函数
            scorescheck1[i] = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );
            if(total_count_para>10){
                scorescheck1[i] -= 0.04*update_mode*(total_count_para-10);
            }
        }

        // 检查数组长度
        if (scorescheck1.length > 25) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck1, scorescheck1.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 25];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck1.length; i++) {
                if (scorescheck1[i] < threshold) {
                    scorescheck1[i] = -99999;
                }
            }
        }

        // 二层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck1[i]>=5000){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_0(reversedBoard);

                scores[i] = -bestAction.score;

            }else{
                scorescheck2[i] = -99999;
            }
        }

        // 检查数组长度
        if (scorescheck2.length > 10) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck2, scorescheck2.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 10];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck2[i] < threshold) {
                    scorescheck2[i] = -99999;
                }
            }
        }

        // 三层打分
        if(cut1 == 2){
            cut1 = 3;
        }
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck2[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_1(reversedBoard);

                scores[i] = -bestAction.score;
            }else{
                scores[i] = -99999;
            }
        }

        // 找出最大分的下标
        int maxIndex = -1;  // 用于存储最大值的下标
        double maxScore = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxIndex = i; // 更新最大值的下标
            }
        }


        double chosenScore = scores[maxIndex];
        int[] chosenPlacePos = actionData.placePositions.get(maxIndex);
        int[] chosenPullPos = actionData.pullPositions.get(maxIndex);
        int[] chosenTargetPos = actionData.targetPositions.get(maxIndex);

        return new ActionResult(chosenScore, chosenPlacePos, chosenPullPos, chosenTargetPos);
    }
    /**
     * 颜色反转函数
     *
     * @param board 输入的棋盘矩阵
     * @return 颜色反转后的棋盘矩阵
     */
    public static int[][] reverseColors(int[][] board) {
        int[][] reversed = new int[15][15];
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                if (board[i][j] == 1) {
                    reversed[i][j] = -1;
                } else if (board[i][j] == -1) {
                    reversed[i][j] = 1;
                } else {
                    reversed[i][j] = 0;
                }
            }
        }
        return reversed;
    }

    public static ActionResult calculateOptimalAction_3(int[][] board) {


        // 初始状态
        BlockData blockDataInitial = storeBlocks(board);

        // 调用打分函数
        double scorecheck = calculateScore(
            blockDataInitial.ownBlockCount,
            blockDataInitial.opponentBlockCount,
            blockDataInitial.ownBlockInfluence,
            blockDataInitial.opponentBlockInfluence,
            blockDataInitial.ownBlockPositions,
            blockDataInitial.opponentBlockPositions,
            blockDataInitial.ownBlockPieceCounts,
            blockDataInitial.opponentBlockPieceCounts,
            blockDataInitial.ownBlockSymmetry,
            blockDataInitial.opponentBlockSymmetry
        );
    
        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;
        LegalActionData actionData = generateLegalActions(board,cut,ifsym);

        int actionCount = actionData.actionCount;

        // 分数向量
        double[] scores = new double[actionCount];
        double[] scorescheck1 = new double[actionCount];
        double[] scorescheck2 = new double[actionCount];
        double[] scorescheck3 = new double[actionCount];


        // 遍历每个合法动作，进行一层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDataInitial, placePos, pullPos, targetPos, update_mode);


            // 调用打分函数
            scorescheck1[i] = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );
            if(total_count_para>10){
                scorescheck1[i] -= 0.04*update_mode*(total_count_para-10);
            }
        }

        // 检查数组长度
        if (scorescheck1.length > 100) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck1, scorescheck1.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 100];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck1.length; i++) {
                if (scorescheck1[i] < threshold) {
                    scorescheck1[i] = -99999;
                }
            }
        }

        // 二层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck1[i]>=5000){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_0(reversedBoard);

                scorescheck2[i] = -bestAction.score;

            }else{
                scorescheck2[i] = -99999;
            }
        }

        // 检查数组长度
        
        if (scorescheck2.length > 20) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck2, scorescheck2.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 20];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck2[i] < threshold) {
                    scorescheck2[i] = -99999;
                }
            }
        }

        // 三层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck2[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_1(reversedBoard);

                scorescheck3[i] = -bestAction.score;
            }else{
                scorescheck3[i] = -99999;
            }
        }


        // 检查数组长度
        
        if (scorescheck3.length > 8) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck3, scorescheck3.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 8];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck3[i] < threshold) {
                    scorescheck3[i] = -99999;
                }
            }
        }

        // 四层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck3[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_2(reversedBoard);

                scores[i] = -bestAction.score;
            }else{
                scores[i] = -99999;
            }
        }

        // 找出最大分的下标
        int maxIndex = -1;  // 用于存储最大值的下标
        double maxScore = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxIndex = i; // 更新最大值的下标
            }
        }


        double chosenScore = scores[maxIndex];
        int[] chosenPlacePos = actionData.placePositions.get(maxIndex);
        int[] chosenPullPos = actionData.pullPositions.get(maxIndex);
        int[] chosenTargetPos = actionData.targetPositions.get(maxIndex);

        return new ActionResult(chosenScore, chosenPlacePos, chosenPullPos, chosenTargetPos);
    }

    public static ActionResult calculateOptimalAction_4(int[][] board) {
        // 初始状态
        BlockData blockDataInitial = storeBlocks(board);
        cut1 = 0;

        // 调用打分函数
        double scorecheck = calculateScore(
            blockDataInitial.ownBlockCount,
            blockDataInitial.opponentBlockCount,
            blockDataInitial.ownBlockInfluence,
            blockDataInitial.opponentBlockInfluence,
            blockDataInitial.ownBlockPositions,
            blockDataInitial.opponentBlockPositions,
            blockDataInitial.ownBlockPieceCounts,
            blockDataInitial.opponentBlockPieceCounts,
            blockDataInitial.ownBlockSymmetry,
            blockDataInitial.opponentBlockSymmetry
        );
    
        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;
        LegalActionData actionData = generateLegalActions(board,cut,ifsym);

        int actionCount = actionData.actionCount;

        // 分数向量
        double[] scores = new double[actionCount];
        double[] scorescheck1 = new double[actionCount];
        double[] scorescheck2 = new double[actionCount];
        double[] scorescheck3 = new double[actionCount];
        double[] scorescheck4 = new double[actionCount];


        // 遍历每个合法动作，进行一层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDataInitial, placePos, pullPos, targetPos, update_mode);


            // 调用打分函数
            scorescheck1[i] = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );
            if(total_count_para>10){
                scorescheck1[i] -= 0.04*update_mode*(total_count_para-10);
            }
        }

        // 检查数组长度
        if (scorescheck1.length > 150) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck1, scorescheck1.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 150];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck1.length; i++) {
                if (scorescheck1[i] < threshold) {
                    scorescheck1[i] = -99999;
                }
            }
        }

        // 二层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck1[i]>=5000){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_0(reversedBoard);

                scorescheck2[i] = -bestAction.score;

            }else{
                scorescheck2[i] = -99999;
            }
        }

        // 检查数组长度
        
        if (scorescheck2.length > 40) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck2, scorescheck2.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 40];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck2[i] < threshold) {
                    scorescheck2[i] = -99999;
                }
            }
        }

        // 三层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck2[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_1(reversedBoard);

                scorescheck3[i] = -bestAction.score;
            }else{
                scorescheck3[i] = -99999;
            }
        }


        // 检查数组长度
        
        if (scorescheck3.length > 8) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck3, scorescheck3.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 8];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck3[i] < threshold) {
                    scorescheck3[i] = -99999;
                }
            }
        }

        // 四层打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck3[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_2(reversedBoard);

                scorescheck4[i] = -bestAction.score;
            }else{
                scorescheck4[i] = -99999;
            }
        }

        // 检查数组长度

        if (scorescheck4.length > 3) {
            // 创建一个临时数组用于排序
            double[] temp = Arrays.copyOf(scorescheck4, scorescheck4.length);
            Arrays.sort(temp); // 默认升序排序

            // 取前 N 大的阈值
            double threshold = temp[temp.length - 3];

            // 保留前 N 大的数字，其他赋值 -99999
            for (int i = 0; i < scorescheck2.length; i++) {
                if (scorescheck4[i] < threshold) {
                    scorescheck4[i] = -99999;
                }
            }
        }

        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // 调用更新合法行动结果函数，得到更新后的棋盘
            int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            if(scorescheck4[i]>=-99990){
                // 颜色反转（1变-1，-1变1）
                int[][] reversedBoard = reverseColors(updatedBoard);

                // 调用打分函数，获取分数
                ActionResult bestAction = calculateOptimalAction_3(reversedBoard);

                scores[i] = -bestAction.score;
            }else{
                scores[i] = -99999;
            }
        }
        // 找出最大分的下标
        int maxIndex = -1;  // 用于存储最大值的下标
        double maxScore = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxIndex = i; // 更新最大值的下标
            }
        }


        double chosenScore = scores[maxIndex];
        int[] chosenPlacePos = actionData.placePositions.get(maxIndex);
        int[] chosenPullPos = actionData.pullPositions.get(maxIndex);
        int[] chosenTargetPos = actionData.targetPositions.get(maxIndex);

        return new ActionResult(chosenScore, chosenPlacePos, chosenPullPos, chosenTargetPos);
    }

    
    public static class BlockData {
        public int ownBlockCount;
        public int opponentBlockCount;
        public int[][] ownBlockInfluence;
        public int[][] opponentBlockInfluence;
        public ArrayList<int[][]> ownBlockPositions;
        public ArrayList<int[][]> opponentBlockPositions;
        public int[] ownBlockPieceCounts;
        public int[] opponentBlockPieceCounts;
        public int[] ownBlockSymmetry;
        public int[] opponentBlockSymmetry;
    
        public BlockData(
            int ownBlockCount,
            int opponentBlockCount,
            int[][] ownBlockInfluence,
            int[][] opponentBlockInfluence,
            ArrayList<int[][]> ownBlockPositions,
            ArrayList<int[][]> opponentBlockPositions,
            int[] ownBlockPieceCounts,
            int[] opponentBlockPieceCounts,
            int[] ownBlockSymmetry,
            int[] opponentBlockSymmetry
        ) {
            this.ownBlockCount = ownBlockCount;
            this.opponentBlockCount = opponentBlockCount;
            this.ownBlockInfluence = ownBlockInfluence;
            this.opponentBlockInfluence = opponentBlockInfluence;
            this.ownBlockPositions = ownBlockPositions;
            this.opponentBlockPositions = opponentBlockPositions;
            this.ownBlockPieceCounts = ownBlockPieceCounts;
            this.opponentBlockPieceCounts = opponentBlockPieceCounts;
            this.ownBlockSymmetry = ownBlockSymmetry;
            this.opponentBlockSymmetry = opponentBlockSymmetry;
        }
    }

    public static BlockData storeBlocks(int[][] board) {
        int ownBlockCount = 0;
        int opponentBlockCount = 0;
        int px = 0;
        int py = 0;
        int newX = 0;
        int newY = 0;
        int currentColor = 0;
        int minX = 15, maxX = -1, minY = 15, maxY = -1;
        int symmetry = 0;

        ArrayList<int[]> ownBlockInfluenceList = new ArrayList<>();
        ArrayList<int[]> opponentBlockInfluenceList = new ArrayList<>();

        ArrayList<int[][]> ownBlockPositions = new ArrayList<>();
        ArrayList<int[][]> opponentBlockPositions = new ArrayList<>();

        ArrayList<Integer> ownBlockPieceCounts = new ArrayList<>();
        ArrayList<Integer> opponentBlockPieceCounts = new ArrayList<>();

        ArrayList<Integer> ownBlockSymmetry = new ArrayList<>();
        ArrayList<Integer> opponentBlockSymmetry = new ArrayList<>();

        // 使用一个访问标记数组取代对board的复制
        boolean[][] visited = new boolean[15][15];

        // 定义8个方向
        int[][] directions = {
            {-1, -1}, {-1, 0}, {-1, 1},
            { 0, -1},           { 0, 1},
            { 1, -1}, { 1, 0}, { 1, 1}
        };

        // 遍历棋盘
        for (int x = 0; x < 15; x++) {
            for (int y = 0; y < 15; y++) {
                currentColor = board[x][y];
                if (currentColor != 0 && !visited[x][y]) {
                    // BFS队列使用LinkedList或ArrayDeque
                    ArrayDeque<int[]> queue = new ArrayDeque<>();
                    ArrayList<int[]> blockPositions = new ArrayList<>();

                    queue.add(new int[]{x, y});
                    visited[x][y] = true;

                    // BFS
                    while (!queue.isEmpty()) {
                        int[] pos = queue.poll(); // O(1)
                        blockPositions.add(pos);
                        px = pos[0];
                        py = pos[1];

                        // 遍历8个方向
                        for (int[] dir : directions) {
                            newX = (int) (px + dir[0]);
                            newY = (int) (py + dir[1]);
                            if (newX >= 0 && newX < 15 && newY >= 0 && newY < 15) {
                                if (!visited[newX][newY] && board[newX][newY] == currentColor) {
                                    visited[newX][newY] = true;
                                    queue.add(new int[]{newX, newY});
                                }
                            }
                        }
                    }

                    // 计算影响范围
                    minX = 15; maxX = -1; minY = 15; maxY = -1;
                    for (int[] pos : blockPositions) {
                        if (pos[0] < minX) minX = pos[0];
                        if (pos[0] > maxX) maxX = pos[0];
                        if (pos[1] < minY) minY = pos[1];
                        if (pos[1] > maxY) maxY = pos[1];
                    }

                    // 扩大影响范围
                    int[] influence = new int[]{
                        (int) (minX - 2),
                        (int) (maxX + 2),
                        (int) (minY - 2),
                        (int) (maxY + 2)
                    };

                    // 将块的位置信息转换为二维数组
                    int size = blockPositions.size();
                    int[][] positionsArray = new int[size][2];
                    for (int i = 0; i < size; i++) {
                        positionsArray[i] = blockPositions.get(i);
                    }

                    // 判断对称性
                    symmetry = isSymmetric(blockPositions, minX, maxX, minY, maxY) ? 1 : 0;

                    // 根据颜色分类处理
                    if (currentColor == 1) {
                        ownBlockCount++;
                        ownBlockInfluenceList.add(influence);
                        ownBlockPositions.add(positionsArray);
                        ownBlockPieceCounts.add(size);
                        ownBlockSymmetry.add(symmetry);
                    } else {
                        opponentBlockCount++;
                        opponentBlockInfluenceList.add(influence);
                        opponentBlockPositions.add(positionsArray);
                        opponentBlockPieceCounts.add(size);
                        opponentBlockSymmetry.add(symmetry);
                    }
                }
            }
        }

        // 转换ArrayList到数组
        int[][] ownBlockInfluence = ownBlockInfluenceList.toArray(new int[ownBlockInfluenceList.size()][]);
        int[][] opponentBlockInfluence = opponentBlockInfluenceList.toArray(new int[opponentBlockInfluenceList.size()][]);

        int[] ownBlockPieceCountsArray = new int[ownBlockPieceCounts.size()];
        for (int i = 0; i < ownBlockPieceCounts.size(); i++) {
            ownBlockPieceCountsArray[i] = (int) (int) ownBlockPieceCounts.get(i);
        }
        
        int[] opponentBlockPieceCountsArray = new int[opponentBlockPieceCounts.size()];
        for (int i = 0; i < opponentBlockPieceCounts.size(); i++) {
            opponentBlockPieceCountsArray[i] = (int) (int) opponentBlockPieceCounts.get(i);
        }
        
        int[] ownBlockSymmetryArray = new int[ownBlockSymmetry.size()];
        for (int i = 0; i < ownBlockSymmetry.size(); i++) {
            ownBlockSymmetryArray[i] = (int) (int) ownBlockSymmetry.get(i);
        }
        
        int[] opponentBlockSymmetryArray = new int[opponentBlockSymmetry.size()];
        for (int i = 0; i < opponentBlockSymmetry.size(); i++) {
            opponentBlockSymmetryArray[i] = (int) (int) opponentBlockSymmetry.get(i);
        }
        

        // 封装输出数据
        return new BlockData(
            ownBlockCount,
            opponentBlockCount,
            ownBlockInfluence,
            opponentBlockInfluence,
            ownBlockPositions,
            opponentBlockPositions,
            ownBlockPieceCountsArray,
            opponentBlockPieceCountsArray,
            ownBlockSymmetryArray,
            opponentBlockSymmetryArray
        );
    }


    public static BlockData storeBlocks_update(BlockData blockDataInitial, int[] placePos, int[] pullPos, int[] targetPos, int update_mode) {

        int[][] checkboard = new int[15][15];
        // for (int i = 0; i < checkboard.length; i++) {
        //     for (int j = 0; j < checkboard[i].length; j++) {
        //         checkboard[i][j] = 0;
        //     }
        // }
        // 深拷贝 BlockData 的字段
        int ownBlockCount = blockDataInitial.ownBlockCount;
        int opponentBlockCount = blockDataInitial.opponentBlockCount;

        // 深拷贝二维数组
        int[][] ownBlockInfluence = new int[blockDataInitial.ownBlockInfluence.length][];
        for (int i = 0; i < blockDataInitial.ownBlockInfluence.length; i++) {
            ownBlockInfluence[i] = Arrays.copyOf(blockDataInitial.ownBlockInfluence[i], blockDataInitial.ownBlockInfluence[i].length);
        }

        int[][] opponentBlockInfluence = new int[blockDataInitial.opponentBlockInfluence.length][];
        for (int i = 0; i < blockDataInitial.opponentBlockInfluence.length; i++) {
            opponentBlockInfluence[i] = Arrays.copyOf(blockDataInitial.opponentBlockInfluence[i], blockDataInitial.opponentBlockInfluence[i].length);
        }

        // 深拷贝 ArrayList<int[][]>
        ArrayList<int[][]> ownBlockPositions = new ArrayList<>();
        for (int[][] positions : blockDataInitial.ownBlockPositions) {
            int[][] copiedPositions = new int[positions.length][];
            for (int i = 0; i < positions.length; i++) {
                copiedPositions[i] = Arrays.copyOf(positions[i], positions[i].length);
            }
            ownBlockPositions.add(copiedPositions);
        }

        ArrayList<int[][]> opponentBlockPositions = new ArrayList<>();
        for (int[][] positions : blockDataInitial.opponentBlockPositions) {
            int[][] copiedPositions = new int[positions.length][];
            for (int i = 0; i < positions.length; i++) {
                copiedPositions[i] = Arrays.copyOf(positions[i], positions[i].length);
            }
            opponentBlockPositions.add(copiedPositions);
        }

        // 深拷贝一维数组
        int[] ownBlockPieceCounts = Arrays.copyOf(blockDataInitial.ownBlockPieceCounts, blockDataInitial.ownBlockPieceCounts.length);
        int[] opponentBlockPieceCounts = Arrays.copyOf(blockDataInitial.opponentBlockPieceCounts, blockDataInitial.opponentBlockPieceCounts.length);

        int[] ownBlockSymmetry = Arrays.copyOf(blockDataInitial.ownBlockSymmetry, blockDataInitial.ownBlockSymmetry.length);
        int[] opponentBlockSymmetry = Arrays.copyOf(blockDataInitial.opponentBlockSymmetry, blockDataInitial.opponentBlockSymmetry.length);

        // 构造新的 BlockData
        BlockData finalblockData = new BlockData(
                ownBlockCount,
                opponentBlockCount,
                ownBlockInfluence,
                opponentBlockInfluence,
                ownBlockPositions,
                opponentBlockPositions,
                ownBlockPieceCounts,
                opponentBlockPieceCounts,
                ownBlockSymmetry,
                opponentBlockSymmetry
        );

        // 自己
        for (int i = (int)(blockDataInitial.ownBlockCount-1); i > -1;  i--) {
            int[] range = blockDataInitial.ownBlockInfluence[i];
            boolean in_influenceset = isininfluence(range, placePos);
            boolean in_influencepull1 = false;
            boolean in_influencepull2 = false;
            if(update_mode == 1){
                in_influencepull1 = isininfluence(range, pullPos);
                in_influencepull2 = isininfluence(range, targetPos);
            }
            if(in_influenceset || in_influencepull1 || in_influencepull2){
                finalblockData.ownBlockCount -= 1;
                finalblockData.ownBlockInfluence = removeRowFromMatrix(finalblockData.ownBlockInfluence,i);
                finalblockData.ownBlockPieceCounts = removeElementFromVector(finalblockData.ownBlockPieceCounts,i);
                finalblockData.ownBlockSymmetry = removeElementFromVector(finalblockData.ownBlockSymmetry,i);
                int[][] positions = finalblockData.ownBlockPositions.get(i);
                for (int[] position : positions) {
                    checkboard[position[0]][position[1]] = 1;
                }
                finalblockData.ownBlockPositions.remove(i);
            }
        }

        // 对方
        if(update_mode == -1){
            for (int i = (int)(blockDataInitial.opponentBlockCount-1); i > -1;  i--) {
                int[] range = blockDataInitial.opponentBlockInfluence[i];
                boolean  in_influencepull1 = isininfluence(range, pullPos);
                boolean  in_influencepull2 = isininfluence(range, targetPos);
                if(in_influencepull1 || in_influencepull2){
                    finalblockData.opponentBlockCount -= 1;
                    finalblockData.opponentBlockInfluence = removeRowFromMatrix(finalblockData.opponentBlockInfluence,i);
                    finalblockData.opponentBlockPieceCounts = removeElementFromVector(finalblockData.opponentBlockPieceCounts,i);
                    finalblockData.opponentBlockSymmetry = removeElementFromVector(finalblockData.opponentBlockSymmetry,i);
                    int[][] positions = finalblockData.opponentBlockPositions.get(i);
                    for (int[] position : positions) {
                        checkboard[position[0]][position[1]] = -1;
                    }
                    finalblockData.opponentBlockPositions.remove(i);
                }
            }
        }

        // 更新变化
        checkboard[placePos[0]][placePos[1]] = 1;
        checkboard[pullPos[0]][pullPos[1]] = 0;
        checkboard[targetPos[0]][targetPos[1]] = update_mode;
        BlockData blockDatanew = storeBlocks(checkboard);

        // 拼装
        finalblockData.opponentBlockCount += blockDatanew.opponentBlockCount;
        finalblockData.ownBlockCount += blockDatanew.ownBlockCount;
        finalblockData.ownBlockPieceCounts = concatenate(finalblockData.ownBlockPieceCounts, blockDatanew.ownBlockPieceCounts);
        finalblockData.opponentBlockPieceCounts = concatenate(finalblockData.opponentBlockPieceCounts, blockDatanew.opponentBlockPieceCounts);
        finalblockData.ownBlockSymmetry = concatenate(finalblockData.ownBlockSymmetry, blockDatanew.ownBlockSymmetry);
        finalblockData.opponentBlockSymmetry = concatenate(finalblockData.opponentBlockSymmetry, blockDatanew.opponentBlockSymmetry);
        finalblockData.ownBlockInfluence = verticalConcatenate(finalblockData.ownBlockInfluence,blockDatanew.ownBlockInfluence);
        finalblockData.opponentBlockInfluence = verticalConcatenate(finalblockData.opponentBlockInfluence,blockDatanew.opponentBlockInfluence);
        finalblockData.ownBlockPositions = verticalConcatenate2(finalblockData.ownBlockPositions,blockDatanew.ownBlockPositions);
        finalblockData.opponentBlockPositions = verticalConcatenate2(finalblockData.opponentBlockPositions,blockDatanew.opponentBlockPositions);

        return finalblockData;
    }

    private static boolean isininfluence(int[] range, int[] checkpos) {
        if(checkpos[0]>=(range[0]+1) && checkpos[0]<=(range[1]-1) && checkpos[1]>=(range[2]+1) && checkpos[1]<=(range[3]-1)){
            return true;
        }
        return false;
    }

    public static int[][] removeRowFromMatrix(int[][] matrix, int index) {

        int[][] newMatrix = new int[matrix.length - 1][];
        for (int i = 0, j = 0; i < matrix.length; i++) {
            if (i != index) {
                newMatrix[j++] = matrix[i];
            }
        }
        return newMatrix;
    }
    public static int[] removeElementFromVector(int[] vector, int index) {

        int[] newVector = new int[vector.length - 1];
        for (int i = 0, j = 0; i < vector.length; i++) {
            if (i != index) {
                newVector[j++] = vector[i];
            }
        }
        return newVector;
    }
    public static int[] concatenate(int[] array1, int[] array2) {
        // 创建一个新数组，长度为两个数组的总和
        int[] result = new int[array1.length + array2.length];

        // 将 array1 的元素复制到 result 中
        System.arraycopy(array1, 0, result, 0, array1.length);

        // 将 array2 的元素复制到 result 中
        System.arraycopy(array2, 0, result, array1.length, array2.length);

        return result;
    }
    public static int[][] verticalConcatenate(int[][] array1, int[][] array2) {
        // 获取拼接后的行数
        int totalRows = (int)(array1.length + array2.length);

        // 假设每个二维数组的列数相同（即 array1[0].length == array2[0].length）
        int[][] result = new int[totalRows][];

        // 将 array1 的行复制到 result 中
        System.arraycopy(array1, 0, result, 0, array1.length);

        // 将 array2 的行复制到 result 中
        System.arraycopy(array2, 0, result, array1.length, array2.length);

        return result;
    }
    public static ArrayList<int[][]> verticalConcatenate2(ArrayList<int[][]> list1, ArrayList<int[][]> list2) {
        // 创建一个新的 ArrayList<int[][]>
        ArrayList<int[][]> result = new ArrayList<>();

        // 遍历 list1，将所有二维数组逐个添加到 result 中
        for (int[][] array : list1) {
            result.add(array);
        }

        // 遍历 list2，将所有二维数组逐个添加到 result 中
        for (int[][] array : list2) {
            result.add(array);
        }

        return result;
    }

    private static boolean isSymmetric(ArrayList<int[]> blockPositions, int minX, int maxX, int minY, int maxY) {
        if (blockPositions.size() <=2) return true;

        int spanX = (int) (maxX - minX);
        int spanY = (int) (maxY - minY);

        // 计算可能的对称轴
        double centerX = minX + spanX /2.0;
        double centerY = minY + spanY /2.0;

        // 检查横向对称
        boolean horizontalSymmetry = true;
        for (int[] pos : blockPositions) {
            double mirrorX = 2 * centerX - pos[0];
            boolean found = false;
            for (int[] p : blockPositions) {
                if (Math.abs(p[0] - mirrorX) < 1e-6 && p[1] == pos[1]) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                horizontalSymmetry = false;
                break;
            }
        }

        // 检查纵向对称
        boolean verticalSymmetry = true;
        for (int[] pos : blockPositions) {
            double mirrorY = 2 * centerY - pos[1];
            boolean found = false;
            for (int[] p : blockPositions) {
                if (p[0] == pos[0] && Math.abs(p[1] - mirrorY) < 1e-6) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                verticalSymmetry = false;
                break;
            }
        }

        // 如果横向或纵向对称，返回true
        if (horizontalSymmetry || verticalSymmetry) return true;

        // 如果x跨度 == y跨度，检查斜向对称
        if (spanX == spanY) {
            // 主对角线对称
            boolean diagonalSymmetry = true;
            for (int[] pos : blockPositions) {
                boolean found = false;
                for (int[] p : blockPositions) {
                    if (p[0]-minX == pos[1]-minY && p[1]-minY == pos[0]-minX) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    diagonalSymmetry = false;
                    break;
                }
            }

            // 副对角线对称
            boolean antiDiagonalSymmetry = true;
            for (int[] pos : blockPositions) {
                boolean found = false;
                for (int[] p : blockPositions) {
                    if (maxX - p[0] == pos[1]-minY && p[1]-minY == maxX - pos[0]) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    antiDiagonalSymmetry = false;
                    break;
                }
            }

            if (diagonalSymmetry || antiDiagonalSymmetry) return true;
        }

        // 如果以上都不满足，对称性判断为不对称
        return false;
    }




    static class LegalAction {
        int[] placePos;    // 落子位置坐标 [x, y]
        int[] pullPos;     // 拉子位置坐标 [x, y]
        int[] targetPos;   // 拉子目标位置坐标 [x, y]

        public LegalAction(int[] placePos, int[] pullPos, int[] targetPos) {
            this.placePos = placePos;
            this.pullPos = pullPos;
            this.targetPos = targetPos;
        }
    }


    /**
     * 合法动作数据类
     */
    public static class LegalActionData {
        int actionCount;          // 合法动作数量
        ArrayList<int[]> placePositions;   // 落子位置列表
        ArrayList<int[]> pullPositions;    // 拉子位置列表
        ArrayList<int[]> targetPositions;  // 拉子目标位置列表

        public LegalActionData(int actionCount, ArrayList<int[]> placePositions,
                               ArrayList<int[]> pullPositions, ArrayList<int[]> targetPositions) {
            this.actionCount = actionCount;
            this.placePositions = placePositions;
            this.pullPositions = pullPositions;
            this.targetPositions = targetPositions;
        }
    }


    public static LegalActionData generateLegalActions(int[][] board, int cut, int ifsym) {
        ArrayList<LegalAction> legalActions = new ArrayList<>();
        int dx = 0;
        int dy = 0;
        int adjX = 0;
        int adjY = 0;
        int tempX = 0;
        int tempY = 0;
        int break1 = 0;
        int steps = 0;
        int targetX = 0;
        int targetY = 0;
        // 定义8个方向（N, NE, E, SE, S, SW, W, NW）
        int[][] directions = {
                {-1, 0}, // N
                {-1, 1}, // NE
                {0, 1},  // E
                {1, 1},  // SE
                {1, 0},  // S
                {1, -1}, // SW
                {0, -1}, // W
                {-1, -1} // NW
        };



        for (int x = 0; x < 15; x++) {
            for (int y = 0; y < 15; y++) {
                if (board[x][y] == 0) { // 找到一个空位，可以尝试落子
                    // 默认动作：落子位置自身，不拉子
                    int[] placePos = {x, y};
                    int[] pullPos = {x, y};
                    int[] targetPos = {x, y};

                    boolean isSurroundedByOwnPiecesres = isSurroundedByOwnPieces(board, x, y);

                    if(total_count_para < 5){
                        LegalAction defaultAction = new LegalAction(placePos, pullPos, targetPos);
                        legalActions.add(defaultAction);
                    }
                    board[x][y] = 1;

                    // 检查8个方向的可能拉子动作
                    if(isSurroundedByOwnPiecesres || cut == 0){
                        int verified = 1;
                        if(!isSurroundedByOwnPiecesres && cut == 0){
                            double randomNumber = Math.random();
                            if(randomNumber >= 0.5){
                                verified = 2;
                            }else{
                                verified = 0;
                            }
                        }
                        if(verified == 1){
                            for (int[] dir : directions) {
                                dx = dir[0];
                                dy = dir[1];
                                adjX = (int) (x + dx);
                                adjY = (int) (y + dy);

                                // 检查相邻位置是否在棋盘内
                                while (isWithinBoard(adjX, adjY)) {
                                    if (board[adjX][adjY] == -1) { // 对方棋子，可以尝试拉动
                                        // 尝试将对方棋子向落子方向拉近一个单位
                                        tempX = (int) (adjX - dx);
                                        tempY = (int) (adjY - dy);
                                        break1 = 0;
                                        while (isWithinBoard(tempX, tempY) && board[tempX][tempY] != 0) {
                                            // 不允许越过落子位置
                                            if (tempX == x && tempY == y) {
                                                break1 = 1;
                                                break;
                                            }
                                            tempX -= dx;
                                            tempY -= dy;
                                        }
                                        if(break1 == 1){
                                            break;
                                        }
                                        if (tempX != x && tempY != y && isWithinBoard(tempX, tempY) && board[tempX][tempY] == 0) {
                                            LegalAction action = new LegalAction(
                                                    placePos,
                                                    new int[]{adjX, adjY},
                                                    new int[]{tempX, tempY}
                                            );
                                            legalActions.add(action);
                                        }

                                    } else if (board[adjX][adjY] == 1 && (cut == 0 || ifsym == 0)) { // 我方棋子，可以尝试拉动
                                        board[adjX][adjY] = 0;
                                        // 可以拉动任意个单位
                                        steps = 1;
                                        while (true) {
                                            targetX = (int) (adjX - dx * steps);
                                            targetY = (int) (adjY - dy * steps);

                                            if (!isWithinBoard(targetX, targetY)) {
                                                break; // 超出棋盘
                                            }

                                            if (targetX == x && targetY == y) {
                                                break; // 目标位置到达
                                            }

                                            // 检查拉子目标位置周围是否有我方棋子
                                            if (board[targetX][targetY] == 0 && isSurroundedByOwnPieces(board, targetX, targetY)) {
                                                LegalAction action = new LegalAction(
                                                        placePos,
                                                        new int[]{adjX, adjY},
                                                        new int[]{targetX, targetY}
                                                );
                                                legalActions.add(action);
                                            }
                                            steps++;
                                        }
                                        board[adjX][adjY] = 1;
                                    }
                                    adjX += dx;
                                    adjY += dy;
                                }
                            }
                        }else if(verified == 2){
                            for (int[] dir : directions) {
                                dx = dir[0];
                                dy = dir[1];
                                adjX = (int) (x + dx);
                                adjY = (int) (y + dy);

                                // 检查相邻位置是否在棋盘内
                                while (isWithinBoard(adjX, adjY)) {
                                    if (board[adjX][adjY] == -1) { // 对方棋子，可以尝试拉动
                                        // 尝试将对方棋子向落子方向拉近一个单位
                                        tempX = (int) (adjX - dx);
                                        tempY = (int) (adjY - dy);
                                        break1 = 0;
                                        while (isWithinBoard(tempX, tempY) && board[tempX][tempY] != 0) {
                                            // 不允许越过落子位置
                                            if (tempX == x && tempY == y) {
                                                break1 = 1;
                                                break;
                                            }
                                            tempX -= dx;
                                            tempY -= dy;
                                        }
                                        if(break1 == 1){
                                            break;
                                        }
                                        if (tempX != x && tempY != y && isWithinBoard(tempX, tempY) && board[tempX][tempY] == 0) {
                                            LegalAction action = new LegalAction(
                                                    placePos,
                                                    new int[]{adjX, adjY},
                                                    new int[]{tempX, tempY}
                                            );
                                            legalActions.add(action);
                                        }

                                    } else if (board[adjX][adjY] == 1) { // 我方棋子，可以尝试拉动

                                        targetX = (int) (x + dx);
                                        targetY = (int) (y + dy);

                                        if (!isWithinBoard(targetX, targetY)) {
                                            break; // 超出棋盘
                                        }

                                        if (board[targetX][targetY] == 0) {
                                            LegalAction action = new LegalAction(
                                                    placePos,
                                                    new int[]{adjX, adjY},
                                                    new int[]{targetX, targetY}
                                            );
                                            legalActions.add(action);
                                        }
                                    }
                                    adjX += dx;
                                    adjY += dy;
                                }
                            }
                        }
                    }
                    board[x][y] = 0;
                }
            }
        }

        // 转换为输出格式
        ArrayList<int[]> placePositions = new ArrayList<>();
        ArrayList<int[]> pullPositions = new ArrayList<>();
        ArrayList<int[]> targetPositions = new ArrayList<>();

        for (LegalAction action : legalActions) {
            placePositions.add(action.placePos);
            pullPositions.add(action.pullPos);
            targetPositions.add(action.targetPos);
        }

        LegalActionData actionData = new LegalActionData(
                legalActions.size(),
                placePositions,
                pullPositions,
                targetPositions
        );

        return actionData;
    }




    /**
     * 检查一个位置是否在棋盘内
     *
     * @param x 横坐标
     * @param y 纵坐标
     * @return 在棋盘内返回true，否则返回false
     */
    public static boolean isWithinBoard(int x, int y) {
        return x >= 0 && x < 15 && y >= 0 && y < 15;
    }

    public static boolean isSurroundedByOwnPieces(int[][] board, int x, int y) {
        int adjX = 0;
        int adjY = 0;
        // 定义8个方向
        int[][] directions = {
                {-1, 0}, // N
                {-1, 1}, // NE
                {0, 1},  // E
                {1, 1},  // SE
                {1, 0},  // S
                {1, -1}, // SW
                {0, -1}, // W
                {-1, -1} // NW
        };

        for (int[] dir : directions) {
            adjX = (int) (x + dir[0]);  // Cast the result to int
            adjY = (int) (y + dir[1]);  // Cast the result to int
            if (isWithinBoard(adjX, adjY)) {
                if (board[adjX][adjY] == 1) {
                    return true;
                }
            }
        }

        return false;
    }



    public static int[][] executeAction(int[][] currentBoard, int[] placePos, int[] pullPos, int[] targetPos) {
        // 深拷贝当前棋盘，避免修改原始棋盘
        int[][] updatedBoard = new int[15][15];
        for (int i = 0; i < 15; i++) {
            updatedBoard[i] = Arrays.copyOf(currentBoard[i], 15);
        }

        // 步骤1：将落子位置赋值为1
        updatedBoard[placePos[0]][placePos[1]] = 1;

        // 保存拉子位置原先的值
        int originalValue = updatedBoard[pullPos[0]][pullPos[1]];

        // 步骤2：将拉子位置赋值为0
        updatedBoard[pullPos[0]][pullPos[1]] = 0;

        // 步骤3：将拉子目标位置赋值为拉子位置原先的值
        updatedBoard[targetPos[0]][targetPos[1]] = originalValue;

        return updatedBoard;
    }



    public static double calculateScore(
            int ownBlockCount,
            int opponentBlockCount,
            int[][] ownBlockInfluence,
            int[][] opponentBlockInfluence,
            ArrayList<int[][]> ownBlockPositions,
            ArrayList<int[][]> opponentBlockPositions,
            int[] ownBlockPieceCounts,
            int[] opponentBlockPieceCounts,
            int[] ownBlockSymmetry,
            int[] opponentBlockSymmetry
    ) {
        double baseScore = 10000;
        // 我方规则分
        double myRuleScore = calculateMyRuleScore(ownBlockSymmetry, ownBlockPieceCounts);
        // 对比规则分
        double compareRuleScore = calculateCompareRuleScore(ownBlockCount, opponentBlockCount);

        double basescore1 = baseScore + myRuleScore + compareRuleScore  + 0.000001 * Math.random();

        if(basescore1 < 5000){
            return basescore1;
        }

        double myScore = calculateFormationScore(ownBlockCount, ownBlockInfluence, ownBlockPieceCounts);
        double opponentScore = calculateFormationScore(opponentBlockCount, opponentBlockInfluence, opponentBlockPieceCounts);

        // 我方和对方的两个块组合惩罚
        myScore += calculatePairPenalty(ownBlockInfluence, ownBlockPieceCounts, ownBlockPositions);
        opponentScore += calculatePairPenalty(opponentBlockInfluence, opponentBlockPieceCounts, opponentBlockPositions);

        // 对方规则分
        double opponentRuleScore = calculateOpponentRuleScore(opponentBlockSymmetry, opponentBlockPieceCounts);

        double finalScore = basescore1 + myScore*paras1[5] - 1.5*opponentScore*paras1[6] + total_count_para2*opponentRuleScore*paras1[7];

        return finalScore;
    }
    /**
     * 根据BlockPositions构造棋盘矩阵
     * 
     * @param blockPositions ArrayList<int[][]>
     *        每个元素为一个二维坐标矩阵，存储若干二维坐标 [x, y]
     *        代表一个棋子块中的所有棋子的位置。
     * @return int[][] 15x15棋盘矩阵
     */
    public static int[][] constructBoard(ArrayList<int[][]> blockPositions) {
        int[][] board = new int[15][15];
        
        for (int[][] block : blockPositions) {
            for (int[] position : block) {
                int x = position[0];
                int y = position[1];
                
                if (x >= 0 && x < 15 && y >= 0 && y < 15) {
                    board[x][y] = 1;
                }
            }
        }
        
        return board;
    }


    /**
     * 计算单方棋型基本分（不包括两个块组合的惩罚）
     */
    private static double calculateFormationScore(int blockCount, int[][] blockInfluence, int[] blockPieceCounts) {
        double score = -0.10 * blockCount*paras1[8];
        // 对块数惩罚
        if (blockCount > 3) {
            score -= 0.2 * (blockCount - 3) *paras1[8];
        }
        if (blockCount > 6) {
            score -= 1.5 * (blockCount - 6) *paras1[9];
        }
        if (blockCount > 8) {
            score -= 3 * (blockCount - 8) *paras1[9];
        }
        // 对每个块的棋子数量进行惩罚
        for (int count : blockPieceCounts) {
            score += pieceCountPenalty(count) *paras1[10] *1.3;
        }

        return score;
    }

    /**
     * 计算两个块组合的接近惩罚
     */
    private static double calculatePairPenalty(int[][] blockInfluence, int[] blockPieceCounts, ArrayList<int[][]> blockPositions) {
        double penaltyFactor = 0;
        double scoreChange = 0.0;
        double closeness = 0;
        int sum = 0;
        for (int i = 0; i < blockInfluence.length; i++) {
            // 边缘
            double closenessedge = calculateClosenessedge(blockInfluence[i],blockPieceCounts[i]);
            scoreChange -= closenessedge;

            for (int j = i+1; j < blockInfluence.length; j++) {
                sum = blockPieceCounts[i] + blockPieceCounts[j];
                penaltyFactor = 0.4 + 0.4*(sum-0.25) *paras1[11];
                if (penaltyFactor > 4) {
                    penaltyFactor = 4;
                }

                closeness = calculateCloseness(blockInfluence[i], blockInfluence[j] , blockPositions.get(i), blockPositions.get(j));
                // 减分
                scoreChange -= (closeness * penaltyFactor);
            }
        }
        return scoreChange;
    }

    /**
     * 计算棋子数量对应的扣分
     */
    private static double pieceCountPenalty(int count) {
        if (count == 1) return -0.40 + 0.5*total_count_para3;
        if (count == 2) return -0.10;
        if (count == 3) return +0.2 + total_count_para3;
        if (count == 4) return -0.75;
        if (count == 5) return -2;
        if (count == 6) return -4;
        if (count == 7) return -6;
        if (count == 8) return -9;
        if (count == 9) return -15;
        if (count >=10) return -15 - 10*(count-9);
        return 0;
    }

    /**
     * 计算两个块之间的接近系数
     *
     * 接近系数计算方法：
     * 假设A块范围：Ax1, Ax2, Ay1, Ay2
     * 假设B块范围：Bx1, Bx2, By1, By2
     *
     * 条件：
     * 若 (Ax1≥Bx2且Ay1≥By2)或(Bx1≥Ax2且By1≥Ay2) 则接近系数=0.4
     * 若 (Ax1>Bx2且Ay1>By2)或(Bx1>Ax2且By1>Ay2) 则接近系数=0.8
     * 否则=0.
     */
    private static double calculateCloseness(int[] blockA, int[] blockB, int[][]posAall, int[][] posBall) {
        int Ax1 = (int) (blockA[0]-1), Ax2 = (int) (blockA[1]+1), Ay1 = (int) (blockA[2]-1), Ay2 = (int) (blockA[3]+1);
        int Bx1 = (int) (blockB[0]), Bx2 = (int) (blockB[1]), By1 = (int) (blockB[2]), By2 = (int) (blockB[3]);

        boolean condGE = false; // 大于等于条件
        double dis_real_para = 0;

        
        
        // 检查≥条件
        if ((Ax1 <= Bx2 && Ay1 <= By2 && Ax2 >= Bx1 && Ay2 >= By1)) {
            condGE = true;
        }

        if(condGE){
            int true_dis = 100;
            int true_dis_num = 0;
            int newdis = 0;
            int newdisx = 0;
            int newdisy = 0;
            for (int[] posA : posAall){
                for(int[] posB : posBall){
                    newdisx = Math.abs(posA[0] - posB[0]);
                    newdisy = Math.abs(posA[1] - posB[1]);
                    if (newdisx <= 4 && newdisy <= 4){
                        newdis = newdisx + newdisy;
                        if (newdis == true_dis) {
                            true_dis_num += 1;
                        }else if(newdis < true_dis){
                            true_dis = newdis;
                            true_dis_num = 1;
                        }
                    }
                }
            }
            if(true_dis<=2){
                dis_real_para = 0.45;
            }else if (true_dis<=3) {
                dis_real_para = 0.35;
            }else if (true_dis<=4) {
                dis_real_para = 0.25;
            }else if (true_dis<=5) {
                dis_real_para = 0.15;
            }else if (true_dis<=6){
                dis_real_para = 0.01;
            }else{
                dis_real_para = 0.05;
            }
            if(true_dis_num>=5){
                dis_real_para *= 1.7;
            }else if (true_dis_num>=4) {
                dis_real_para *= 1.5;
            }else if (true_dis_num>=3) {
                dis_real_para *= 1.3;
            }else if (true_dis_num>=2) {
                dis_real_para *= 1.2;
            }
        }
        

        return dis_real_para*paras1[14];

    }

    private static double calculateClosenessedge(int[] blockA, int posnum) {
        int Ax1 = blockA[0], Ax2 = blockA[1], Ay1 = blockA[2], Ay2 = blockA[3];
        double resul1 = 0;
        if(Ax1==-2 || Ax2==16){
            resul1 += 0.03;
            if(posnum > 2){
                resul1 += 0.01*(posnum-2);
            }
        }else if(Ax1==-1 || Ax2==15){
            resul1 -= 0.01;
        }else if(Ax1==0 || Ax2==14){
            resul1 -= 0.05;
        }

        if(Ay1==-2 || Ay2==16){
            resul1 += 0.03;
            if(posnum > 2){
                resul1 += 0.01*(posnum-2);
            }
        }else if(Ay1==-1 || Ay2==15){
            resul1 -= 0.01;
        }else if(Ay1==0 || Ay2==14){
            resul1 -= 0.05;
        }

        double resul2 = 0;
        int x_length = Ax2 - Ax1 - 3;
        int y_length = Ay2 - Ay1 - 3;
        int diff = Math.abs(x_length - y_length);
        int sum = x_length + y_length;
        double ratio = x_length*y_length/posnum;
        if(diff > 2){
            resul2 += (diff - 2) * (posnum+3) * 0.09;
        }
        if(sum > 3){
            resul2 += (sum - 2) * (posnum) * 0.03;
        }
        if(ratio < 0.5){
            resul2 += (0.5 - ratio) * posnum * 0.08;
        }


        return resul1*posnum*paras1[12] + resul2*paras1[13];
    }
    /**
     * 我方规则分算法：
     * 若存在非对称棋块-> -50000，否则0
     */
    private static double calculateMyRuleScore(int[] ownBlockSymmetry, int[] ownBlockPieceCounts) {
        for (int i=0; i<ownBlockSymmetry.length; i++) {
            if (ownBlockSymmetry[i] == 0) { // 非对称
                return -50000;
            }
        }
        return 0;
    }

    /**
     * 对方规则分算法：
     * 若存在非对称棋块则根据非对称棋块总棋子数加分：
     * <=3 -> 0.3
     * 4->0.33
     * 5->1.1
     * 6->1.7
     * 7->3
     * 8->5
     * 9->15
     * >9->15+11*(sum_nt-9)
     *
     * 无非对称块->0
     */
    private static double calculateOpponentRuleScore(int[] opponentBlockSymmetry, int[] opponentBlockPieceCounts) {
        int sum_nt = 0;
        for (int i=0; i<opponentBlockSymmetry.length; i++) {
            if (opponentBlockSymmetry[i] == 0) {
                sum_nt += opponentBlockPieceCounts[i];
            }
        }
        if (sum_nt == 0) return 0; // 无非对称块
        if (sum_nt <= 3) return 4;
        if (sum_nt ==4) return 8;
        if (sum_nt ==5) return 16;
        if (sum_nt ==6) return 25;
        if (sum_nt ==7) return 31;
        if (sum_nt ==8) return 37;
        if (sum_nt ==9) return 42;
        if (sum_nt >9) return 42 + 6*(sum_nt-9);
        return 0;
    }

    /**
     * 对比规则分算法：
     * 若我方块数<9 且对方块数≥9 -> +1
     * 若我方块数≥9 且 >对方块数 -> -5000
     * 若我方块数≥9 且 =对方块数 -> -1
     * 若我方块数≥9 且 <对方块数 -> +1.1*(对方块数-我方块数)
     */
    private static double calculateCompareRuleScore(int ownBlockCount, int opponentBlockCount) {
        double score = opponentBlockCount - ownBlockCount;
        if(opponentBlockCount>=5 || ownBlockCount>=5){
            score *= 1.5;
        }
        if(opponentBlockCount>=7 || ownBlockCount>=7){
            score *= 1.5;
        }
        if (ownBlockCount <9 && opponentBlockCount>=9) {
            score += 1*paras1[0];
        } else if (ownBlockCount>=9 && ownBlockCount>opponentBlockCount) {
            score -= 10000;
        } else if (ownBlockCount>=9 && ownBlockCount==opponentBlockCount) {
            score -= 1*paras1[1];
        } else if (ownBlockCount>=9 && ownBlockCount<opponentBlockCount) {
            score += 1.1*(opponentBlockCount - ownBlockCount)*paras1[2];
        }
        return score;
    }

    private static double finalcalculateScore1(int[][] board) {

        BlockData blockDatacheck = storeBlocks(board);

        // 调用打分函数
        double scorecheck = calculateScore(
                blockDatacheck.ownBlockCount,
                blockDatacheck.opponentBlockCount,
                blockDatacheck.ownBlockInfluence,
                blockDatacheck.opponentBlockInfluence,
                blockDatacheck.ownBlockPositions,
                blockDatacheck.opponentBlockPositions,
                blockDatacheck.ownBlockPieceCounts,
                blockDatacheck.opponentBlockPieceCounts,
                blockDatacheck.ownBlockSymmetry,
                blockDatacheck.opponentBlockSymmetry
        );

        int ifsym = 1;
        if(scorecheck<=-15000){
            ifsym = 0;
        }

        int cut = 0;

        LegalActionData actionData = generateLegalActions(board,cut,ifsym);
        int actionCount = actionData.actionCount;
        double[] scores = new double[actionCount];
        // 遍历每个合法动作，进行打分
        for (int i = 0; i < actionCount; i++) {
            int[] placePos = actionData.placePositions.get(i);
            int[] pullPos = actionData.pullPositions.get(i);
            int[] targetPos = actionData.targetPositions.get(i);

            // // 调用更新合法行动结果函数，得到更新后的棋盘
            // int[][] updatedBoard = executeAction(board, placePos, pullPos, targetPos);

            // 分块存储
            int update_mode = board[pullPos[0]][pullPos[1]];
            if(update_mode == 0){
                update_mode = 1;
            }
            BlockData blockData = storeBlocks_update(blockDatacheck, placePos, pullPos, targetPos, update_mode);;

            // 调用打分函数
            double score = calculateScore(
                    blockData.ownBlockCount,
                    blockData.opponentBlockCount,
                    blockData.ownBlockInfluence,
                    blockData.opponentBlockInfluence,
                    blockData.ownBlockPositions,
                    blockData.opponentBlockPositions,
                    blockData.ownBlockPieceCounts,
                    blockData.opponentBlockPieceCounts,
                    blockData.ownBlockSymmetry,
                    blockData.opponentBlockSymmetry
            );

            scores[i] = score;
        }

        // 找出最大分
        double maxScore = Double.NEGATIVE_INFINITY;
        for (double s : scores) {
            if (s > maxScore) {
                maxScore = s;
            }
        }

        if(maxScore<5000){
            maxScore = -99999;
        }

        return maxScore;
    }



















    // 附加部分

    public static void printBoardWithAction(int[][] board, ActionResult action) {
        // ANSI颜色码
        final String RED_BG = "\u001B[41m";    // 红底
        final String GREEN_BG = "\u001B[42m";  // 绿底
        final String YELLOW_BG = "\u001B[43m"; // 黄底
        final String RESET = "\u001B[0m";

        int[] placePos = action.placePos;
        int[] pullPos = action.pullPos;
        int[] targetPos = action.targetPos;

        System.out.println("带动作标注的棋盘(红底=落子位置, 绿底=被拉子位置, 黄底=拉子结果位置):");
        System.out.print("   ");
        for (int c = 0; c < 15; c++) {
            System.out.printf("%2s ", (char) ('a' + c));
        }
        System.out.println();

        for (int r = 0; r < 15; r++) {
            System.out.printf("%2d ", r+1);
            for (int c = 0; c < 15; c++) {
                String symbol = getSymbol(board[r][c]);
                String cellStr = " " + symbol + " ";

                // 判断是否为落子/拉子/拉子目标位置，添加底色
                if (r == placePos[0] && c == placePos[1]) {
                    cellStr = RED_BG + cellStr + RESET;
                } else if (r == pullPos[0] && c == pullPos[1]) {
                    cellStr = GREEN_BG + cellStr + RESET;
                } else if (r == targetPos[0] && c == targetPos[1]) {
                    cellStr = YELLOW_BG + cellStr + RESET;
                }

                System.out.print(cellStr);
            }
            System.out.println();
        }
    }

    /**
     * 根据棋盘值返回对应符号：1=黑棋(●), -1=白棋(○), 0=空位(+)
     */
    private static String getSymbol(int val) {
        if (val == 1) return "●";
        if (val == -1) return "○";
        return ".";
    }



    public static double count_total_num(int[][] board){
        double num = 0;
        for (int x = 0; x < 15; x++) {
            for (int y = 0; y < 15; y++) {
                if(board[x][y] != 0){
                    num += 1;
                }
            }
        }


        return num;
    }

}
